package ge.tsu.java.project.server;

import ge.tsu.java.project.commons.Contact;
import ge.tsu.java.project.commons.Logger;
import ge.tsu.java.project.commons.Message;
import ge.tsu.java.project.commons.Contact.Status;
import ge.tsu.java.project.commons.Message.Type;
import ge.tsu.java.project.commons.Protocol;

import java.io.IOException;
import java.util.ArrayList;

public class ClientProcessor {

	private static Logger LOGGER = Logger.getInstance(ClientProcessor.class);
	
	private Protocol protocol;
	private Client client;
	private ClientProcessorEngine engine = new MockCPEngine(); // TODO remove hardcoded
	private boolean loop;

	public ClientProcessor(Protocol protocol) {
		this.protocol = protocol;
	}

	public Client getClient() {
		return client;
	}
	
	public Protocol getProtocol() {
		return protocol;
	}
	
	public void process() throws IOException {
		loop = true;
		while (loop) {
			doProcess();
			if (Thread.interrupted()) {
				return;
			}
		}
	}

	private void doProcess() throws IOException {
		Type messageType = protocol.readMessage().getType();
		switch (messageType) {
		case AUTHENTICATE:
			doAuthenticate();
			break;
		case CHAT_MESSAGE:
			doSendChatMessage();
			break;
		case REGISTER:
			doRegister();
			break;
		case GET_CONTACT_LIST:
			doSendContactList();
			break;
		case EOF:
			Server.removeClient(client);
			loop = false;
			break;
		default:
			break;
		}
	}

	private void doSendContactList() throws IOException {
		String userId = protocol.readString();
		ArrayList<Contact> contacts = engine.getContactsOf(userId);
		synchronized (protocol) {
			protocol.writeSerializable(contacts);
		}
	}

	private void doRegister() throws IOException {
		String userId = protocol.readString();
		String passwd = protocol.readString();
		boolean success = engine.register(userId, passwd);
		synchronized (protocol) {
			protocol.writeBoolean(success);
		}
	}

	private void doSendChatMessage() throws IOException {
		String chatMessage = protocol.readString();
		String dsClienttId = protocol.readString();
		Client dstClient = Server.findClient(dsClienttId);
		if (dstClient != null) {
			Protocol clientProtocol = dstClient.getProtocol();
			synchronized (clientProtocol) {
				clientProtocol.writeMessage(Message.newMessage(Type.CHAT_MESSAGE));
				clientProtocol.writeString(chatMessage);
				clientProtocol.writeSerializable(client.toContact(Status.ONLINE));
			}
		} else {
			LOGGER.log("Cannot find online client with id: " + dsClienttId); // gone offline?
		}
	}

	private void doAuthenticate() throws IOException {
		if (client != null) {
			return;
		}
		String userId = protocol.readString();
		String passwd = protocol.readString();
		boolean success = engine.authenticate(userId, passwd);
		if (success) {
			client = new Client(userId);
			client.setProcessor(this);
			Server.addClient(client);
		}
		synchronized (protocol) {
			protocol.writeBoolean(success);
		}
	}

}
